﻿#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Authorization.Security/ClaimsExtensions 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       N/A
* 类 名：       ClaimsExtensions
* 创建时间：  2025/5/24 10:40:49
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace SSPivot.Authorization.Security
{
    public static class ClaimsIdentityExtensions
    {
        public static long? FindUserId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var userIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.UserId);
            if (userIdOrNull == null || userIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(userIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindUserId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var userIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.UserId);
            if (userIdOrNull == null || userIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(userIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindTenantId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var tenantIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.TenantId);
            if (tenantIdOrNull == null || tenantIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(tenantIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }
        public static string? FindTenantName([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var tenantNameOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.TenantName);
            if (tenantNameOrNull == null || tenantNameOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            return tenantNameOrNull.Value;
        }

        public static long? FindTenantId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var tenantIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.TenantId);
            if (tenantIdOrNull == null || tenantIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(tenantIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static string FindClientId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var clientIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ClientId);
            if (clientIdOrNull == null || clientIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            return clientIdOrNull.Value;
        }

        public static string FindClientId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var clientIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ClientId);
            if (clientIdOrNull == null || clientIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            return clientIdOrNull.Value;
        }

        public static long? FindEditionId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var editionIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.EditionId);
            if (editionIdOrNull == null || editionIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(editionIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindEditionId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var editionIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.EditionId);
            if (editionIdOrNull == null || editionIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(editionIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindImpersonatorTenantId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var impersonatorTenantIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ImpersonatorTenantId);
            if (impersonatorTenantIdOrNull == null || impersonatorTenantIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(impersonatorTenantIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindImpersonatorTenantId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var impersonatorTenantIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ImpersonatorTenantId);
            if (impersonatorTenantIdOrNull == null || impersonatorTenantIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(impersonatorTenantIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindImpersonatorUserId([NotNull] this ClaimsPrincipal principal)
        {
            Check.NotNullVoid(principal, nameof(principal));

            var impersonatorUserIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ImpersonatorUserId);
            if (impersonatorUserIdOrNull == null || impersonatorUserIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(impersonatorUserIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static long? FindImpersonatorUserId([NotNull] this IIdentity identity)
        {
            Check.NotNullVoid(identity, nameof(identity));

            var claimsIdentity = identity as ClaimsIdentity;

            var impersonatorUserIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == SSPivotClaimTypes.ImpersonatorUserId);
            if (impersonatorUserIdOrNull == null || impersonatorUserIdOrNull.Value.IsNullOrWhiteSpace())
            {
                return null;
            }

            if (long.TryParse(impersonatorUserIdOrNull.Value, out var guid))
            {
                return guid;
            }

            return null;
        }

        public static ClaimsIdentity AddIfNotContains(this ClaimsIdentity claimsIdentity, Claim claim)
        {
            Check.NotNullVoid(claimsIdentity, nameof(claimsIdentity));

            if (!claimsIdentity.Claims.Any(x => string.Equals(x.Type, claim.Type, StringComparison.OrdinalIgnoreCase)))
            {
                claimsIdentity.AddClaim(claim);
            }

            return claimsIdentity;
        }

        public static ClaimsIdentity AddOrReplace(this ClaimsIdentity claimsIdentity, Claim claim)
        {
            Check.NotNullVoid(claimsIdentity, nameof(claimsIdentity));

            foreach (var x in claimsIdentity.FindAll(claim.Type).ToList())
            {
                claimsIdentity.RemoveClaim(x);
            }

            claimsIdentity.AddClaim(claim);

            return claimsIdentity;
        }

        public static ClaimsPrincipal AddIdentityIfNotContains([NotNull] this ClaimsPrincipal principal, ClaimsIdentity identity)
        {
            Check.NotNullVoid(principal, nameof(principal));

            if (!principal.Identities.Any(x => string.Equals(x.AuthenticationType, identity.AuthenticationType, StringComparison.OrdinalIgnoreCase)))
            {
                principal.AddIdentity(identity);
            }

            return principal;
        }
    }
}
